/*
 * Copyright 2005-2013 finalist.cn. All rights reserved.
 * Support: http://www.finalist.cn
 * License: http://www.finalist.cn/license
 */
package com.finalist.controller.travel.weixin;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.JDOMException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.finalist.Setting;
import com.finalist.controller.shop.BaseController;
import com.finalist.entity.Order;
import com.finalist.entity.OrderItem;
import com.finalist.entity.Payment;
import com.finalist.entity.Product;
import com.finalist.entity.Review;
import com.finalist.entity.Sn;
import com.finalist.entity.Order.OrderStatus;
import com.finalist.entity.Order.PaymentStatus;
import com.finalist.entity.Order.ShippingStatus;
import com.finalist.entity.Payment.Method;
import com.finalist.entity.Payment.Status;
import com.finalist.entity.Payment.Type;
import com.finalist.interceptor.WeixinInterceptor;
import com.finalist.plugin.PaymentPlugin;
import com.finalist.plugin.PaymentPlugin.NotifyMethod;
import com.finalist.plugin.alipayBank.mobile.alipay.config.AlipayConfig;
import com.finalist.plugin.alipayBank.mobile.alipay.util.AlipayNotify;
import com.finalist.plugin.alipayBank.mobile.alipay.util.AlipaySubmit;
import com.finalist.plugin.weixin.ConfigUtils;
import com.finalist.plugin.weixin.WXJSPay;
import com.finalist.plugin.weixin.WeiXinSignAndPackage;
import com.finalist.plugin.weixin.util.XMLUtil;
import com.finalist.service.MemberService;
import com.finalist.service.OrderItemService;
import com.finalist.service.OrderService;
import com.finalist.service.PaymentService;
import com.finalist.service.ProductService;
import com.finalist.service.ReviewService;
import com.finalist.service.SnService;
import com.finalist.util.DateUtil;
import com.finalist.util.SettingUtils;
import com.finalist.util.WebUtils;

/**
 * Controller  订单
 * 
 * @author Finalist IT Group
 * @version 3.0
 */
@Controller("travelWeixinPaymentController")
@RequestMapping("/travel/weixin/payment")
public class PaymentController extends BaseController
{
	protected static final String VIEW = "/travel/weixin/payment/";
	
	 @Resource(name = "productServiceImpl")
	 private ProductService productService;
	 @Resource(name = "memberServiceImpl")
	 private MemberService memberService;
	 @Resource(name = "orderServiceImpl")
	 private OrderService orderService;
	 @Resource(name = "orderItemServiceImpl")
	 private OrderItemService orderItemService;
	 
	 @Resource(name = "paymentServiceImpl")
	 private PaymentService paymentService;
	 
	 protected Setting setting = SettingUtils.get();

	 @Resource(name = "snServiceImpl")
	 private SnService snService;
	 
	 private static final String  ALIPAY_GATEWAY_NEW = "http://wappaygw.alipay.com/service/rest.htm?";
	 private String merchant_url =setting.getSiteUrl()+"/travel/weixin/index.jhtml";
	 private static final Log log = LogFactory.getLog(PaymentController.class);

	 /**
     * 支付
     */
    @RequestMapping(value = "/pay", method = RequestMethod.GET)
    public String createOrder(String sn,String paymentPluginId,ModelMap model,HttpServletRequest request)
    {
    	if(sn==null||paymentPluginId==null){
    		return ERROR_VIEW;
    	}
    	Order order=orderService.findBySn(sn);
    	if(order==null){
    		return ERROR_VIEW;
    	}
    	if(order.getPaymentStatus().equals(PaymentStatus.paid)){
    		//return "redirect:/travel/weixin/order/orderDetail.jhtml?orderId="+order.getId();
    		return ERROR_VIEW;
    	}
		Payment payment = new Payment();
		payment.setSn(snService.generate(Sn.Type.payment));
		payment.setType(Type.payment);
		payment.setMethod(Method.online);
		payment.setStatus(Status.wait);
		if(order!=null&&order.getOrderItems()!=null&&order.getOrderItems().size()!=0){
			Product product=order.getOrderItems().get(0).getProduct();
			if(product.getDefaultDateString()==null){
				return ERROR_VIEW;
			}
			payment.setAdminId(product.getAdmin().getId());
			if(product!=null&&product.getName()!=null){
				payment.setSubject(product.getName());
			}else{
				payment.setSubject("travel");
			}
		}else{
			payment.setSubject("travel");
		}
		if(paymentPluginId!=null&&paymentPluginId.equals("weixin")){
			payment.setPaymentMethod("微信支付");
		}else if(paymentPluginId!=null&&paymentPluginId.equals("ali")){
			payment.setPaymentMethod("支付宝支付");
		}
		payment.setFee(new BigDecimal(0l));
		payment.setAmount(order.getAmount());
		if(order!=null&&order.getOrderItems()!=null&&order.getOrderItems().size()!=0){
			Product product=order.getOrderItems().get(0).getProduct();
			payment.setAdminId(product.getAdmin().getId());
			if(product!=null&&product.getName()!=null&&product.getName().equals("罗平油菜花行摄活动（支付测试）")){
				payment.setAmount(new BigDecimal(0.01));
			}
		}
		payment.setPaymentPluginId(paymentPluginId);
		payment.setExpire(DateUtils.addMinutes(new Date(), 45));
		payment.setOrder(order);
		paymentService.save(payment);
		
    	if(paymentPluginId!=null&&paymentPluginId.equals("ali")){
    		String req_dataToken = "<direct_trade_create_req><notify_url>" + this.getNotifyUrl(payment.getSn(), NotifyMethod.async) + "</notify_url><call_back_url>" + this.getNotifyUrl(payment.getSn(), NotifyMethod.general) + "</call_back_url><seller_account_name>" + AlipayConfig.seller_email + "</seller_account_name><out_trade_no>" + payment.getSn() + "</out_trade_no><subject>" + payment.getSubject() + "</subject><total_fee>" + payment.getAmount().longValue() + "</total_fee><merchant_url>" + merchant_url + "</merchant_url></direct_trade_create_req>";
    		Map<String, String> sParaTempToken = new HashMap<String, String>();
    		sParaTempToken.put("service", "alipay.wap.trade.create.direct");
    		sParaTempToken.put("partner", AlipayConfig.partner);
    		sParaTempToken.put("_input_charset", AlipayConfig.input_charset);
    		sParaTempToken.put("sec_id", AlipayConfig.sign_type);
    		sParaTempToken.put("format", "xml");
    		sParaTempToken.put("v", "2.0");
    		sParaTempToken.put("req_id", payment.getSn());
    		sParaTempToken.put("req_data", req_dataToken);
    		
    		try {
    			String sHtmlTextToken = AlipaySubmit.buildRequest(ALIPAY_GATEWAY_NEW,"", "",sParaTempToken);
    			sHtmlTextToken = URLDecoder.decode(sHtmlTextToken,AlipayConfig.input_charset);
    			String request_token = AlipaySubmit.getRequestToken(sHtmlTextToken);
    			log.info("request_token"+request_token);
    			String req_data = "<auth_and_execute_req><request_token>" + request_token + "</request_token></auth_and_execute_req>";
    			Map<String, String> sParaTemp = new HashMap<String, String>();
    			sParaTemp.put("service", "alipay.wap.auth.authAndExecute");
    			sParaTemp.put("partner", AlipayConfig.partner);
    			sParaTemp.put("_input_charset", AlipayConfig.input_charset);
    			sParaTemp.put("sec_id", AlipayConfig.sign_type);
    			sParaTemp.put("format", "xml");
    			sParaTemp.put("v", "2.0");
    			sParaTemp.put("req_data", req_data);
    			String sHtmlText = AlipaySubmit.buildRequest(ALIPAY_GATEWAY_NEW, sParaTemp, "get", "确认");
    			model.put("sHtmlText", sHtmlText);
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}

            return VIEW+"aliSubmit";
    	}else{
    		Map<String, String> wxPayParamMap = null;
    		String openid=WebUtils.getCookie(request, ConfigUtils.APPID+"openid");
    		
			try {
				wxPayParamMap = WXJSPay.jsApiPay(openid, payment.getAmount().multiply(new BigDecimal(100)).longValue()+"",payment.getSn(),payment.getSubject());
			} catch (JDOMException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}//测试金额为1分钱
    		
			model.put("appId", wxPayParamMap.get("appId"));
			model.put("timeStamp", wxPayParamMap.get("timeStamp"));
			model.put("nonceStr", wxPayParamMap.get("nonceStr"));
			model.put("wxPackage", wxPayParamMap.get("package"));
			model.put("signType", wxPayParamMap.get("signType"));
			model.put("paySign", wxPayParamMap.get("paySign"));
			model.put("payMoney", wxPayParamMap.get("payMoney"));
			model.put("sn", payment.getSn());
    		return VIEW +"weixinSubmit";
    	}
		
    }
    
    /**
	 * 支付回调
	 */
	@RequestMapping("/notify/{notifyMethod}/{sn}")
	public String notify(@PathVariable NotifyMethod notifyMethod, @PathVariable String sn, HttpServletRequest request, ModelMap model) {
		log.info("支付通知接口=====收款单号："+sn);
		try {
			Map<String,String> params = new HashMap<String,String>();
			Map requestParams = request.getParameterMap();
			for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for (int i = 0; i < values.length; i++) {
					valueStr = (i == values.length - 1) ? valueStr + values[i]
							: valueStr + values[i] + ",";
				}
				valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
				params.put(name, valueStr);
			}
			String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
			String result = new String(request.getParameter("result").getBytes("ISO-8859-1"),"UTF-8");
			
			boolean verify_result =false;
			
			if(notifyMethod.equals(NotifyMethod.async)){
				verify_result=AlipayNotify.verifyNotify(params);
			}else{
				verify_result = AlipayNotify.verifyReturn(params);
			}
			
			model.put("result", result);
			if(verify_result&&out_trade_no!=null&&out_trade_no.equals(sn)&&result!=null&&result.equals("success")){//验证成功
				log.info("支付校验成功");
				Payment payment = paymentService.findBySn(sn);
				if (payment != null) {
					Order order=payment.getOrder();
					if(order!=null){
						order.setPaymentStatus(PaymentStatus.paid);
						orderService.update(order);
						model.put("order", order);
					}
					payment.setStatus(Status.success);
					paymentService.update(payment);
					model.addAttribute("payment", payment);
				}
			}else{
				log.info("支付校验失败");
			}
		} catch (UnsupportedEncodingException e) {
			log.info("支付通知异常");
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		log.info("支付通知结束！");
		return VIEW+"notify";
	}
	
	@RequestMapping("/toConfirm")
	public String toConfirm(ModelMap model,String sn){
		Payment payment = paymentService.findBySn(sn);
		model.put("payment", payment);
		model.put("order", payment.getOrder());
		return VIEW+"notify";
	}
	
	@RequestMapping("/weixinnotify")
	public void weixinnotify(ModelMap model,HttpServletRequest request,HttpServletResponse response) {
	log.info("start callback");
		InputStream inStream=null;
		ByteArrayOutputStream outSteam=null;
     try {
    	   inStream = request.getInputStream();
    	   outSteam = new ByteArrayOutputStream();
    	  byte[] buffer = new byte[1024];
    	  int len = 0;
		  while ((len = inStream.read(buffer)) != -1) {
		     outSteam.write(buffer, 0, len);
		  }
		 
	      String result  = new String(outSteam.toByteArray(),"utf-8");
	      log.info("result"+result);
	      Map<String, String> map = XMLUtil.doXMLParse(result);
	      //Map signMap=new HashMap<String, String>();
	   
	      String out_trade_no=map.get("out_trade_no");
	      String result_code=map.get("result_code");
	      
	      log.info("pagrams:"+"result_code"+result_code+"out_trade_no"+out_trade_no);
	      if(result_code!=null&&result_code.equals("SUCCESS")&&out_trade_no!=null){
	    	  log.info("ok le");
	    	  String sn=out_trade_no;
		    	Payment payment = paymentService.findBySn(sn);
		    	if (payment != null) {
		    		Order order=payment.getOrder();
		    		if(order!=null){
		    			order.setPaymentStatus(PaymentStatus.paid);
		    			orderService.update(order);
		    			//model.put("order", order);
		    		}
		    		payment.setStatus(Status.success);
		    		paymentService.update(payment);
		    		log.info("status update success");
		    		//model.addAttribute("payment", payment);
		    		//return VIEW+"notify";
		    	}
	      }
	    /* for(Object keyValue : map.keySet()){
	         log.info("get callBack info"+keyValue+"="+map.get(keyValue));
	     }*/
	} catch (IOException e) {
		log.info("first Exception");
		e.printStackTrace();
	} catch (JDOMException e) {
		log.info("second Exception");
		e.printStackTrace();
	}finally{
		try {
			inStream.close();
			outSteam.close();
		} catch (IOException e) {
			log.info("thired Exception");
			e.printStackTrace();
		}
	}
	//return ERROR_VIEW;
	}

	protected String getNotifyUrl(String sn, NotifyMethod notifyMethod) {
		if (notifyMethod == null) {
			return setting.getSiteUrl() + "/travel/weixin/payment/notify/" + NotifyMethod.general + "/" + sn + ".jhtml";
		}
		return setting.getSiteUrl() + "/travel/weixin/payment/notify/" + notifyMethod + "/" + sn + ".jhtml";
	}
}